package com.ruoyi.common.utils.file;


import com.itextpdf.text.Font;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.poifs.filesystem.FileMagic;
import org.apache.commons.io.IOUtils;

import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.stereotype.Component;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;

import java.io.*;
import java.awt.Color;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.zip.*;

/**
 * 4 步流水线：
 * 1. 原样复制 zip
 * 2. 依次解压每个 Excel（多 Sheet）
 * 3. 按 Sheet 名称 + 表头文字 精准改字段
 * 4. 统一重算公式 → 写回 zip
 * 5. 将Excel转换为PDF并添加到zip
 */
@Component
public class ZipExcelRefineModifier {

    /**
     * @param zipPath     上传 zip 路径
     * @param outDir      输出目录
     * @param sheetFilter Sheet 名称正则（null = 全部）
     * @param headFilter  表头文字正则（null = 全部）
     * @return 包含targetDir和supplierCompany的Map
     */
    public static Map<String, String> modify(String zipPath,
                                String outDir,
                                List<String> sheetFilter,
                                String headFilter
                               ) throws IOException, DocumentException {
        File outFolder = new File(outDir);
        if (!outFolder.exists()) outFolder.mkdirs();

        // 1) 解压并复制 Excel 到工作目录
        File workDir = new File(outFolder, "excel_mod_" + UUID.randomUUID());
        workDir.mkdirs();

        Map<String, String> resultMap = new HashMap<>();

        // 处理原始ZIP文件中的Excel
        List<Charset> charsetCandidates = Arrays.asList(
                Charset.forName("UTF-8"),
                Charset.forName("GBK"),
                Charset.forName("CP437")
        );

        boolean processed = false;
        IllegalArgumentException lastIllegal = null;
        for (Charset cs : charsetCandidates) {
            ZipFile zf = null;
            try {
                zf = new ZipFile(zipPath, cs);
                processZipEntries(zf, workDir, resultMap);
                processed = true;
                break;
            } catch (IllegalArgumentException iae) {
                lastIllegal = iae; // 记录并尝试下一个 charset
            } finally {
                if (zf != null) try {
                    zf.close();
                } catch (IOException ignore) {
                }
            }
        }
        if (!processed) {
            if (lastIllegal != null) throw lastIllegal; // 维持原始异常类型
            throw new IOException("Failed to read zip with all charset candidates");
        }

        // 3) 将更改后的所有 Excel 重新打成 zip
        File newZipFile = new File(outFolder, "modified_" + System.currentTimeMillis() + ".zip");
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(newZipFile))) {
            // 添加Excel文件
            zipFolderRecursively(workDir, workDir, zos);
        }

        // 生成上游PDF（原始zipPath）
        File upstreamPdfFile = new File(workDir, "upstream_excel_contents.pdf");
        generatePdfFromZip(zipPath, upstreamPdfFile);

        // 生成下游PDF（新生成的zip）
        File downstreamPdfFile = new File(workDir, "downstream_excel_contents.pdf");
        generatePdfFromZip(newZipFile.getAbsolutePath(), downstreamPdfFile);

        // 重新打包，加入生成的PDF文件
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(newZipFile))) {
            // 添加Excel文件
            zipFolderRecursively(workDir, workDir, zos);

            // 添加上游PDF文件
            if (upstreamPdfFile.exists() && upstreamPdfFile.length() > 0) {
                String entryName = "upstream_excel_contents.pdf";
                zos.putNextEntry(new ZipEntry(entryName));
                try (InputStream is = new FileInputStream(upstreamPdfFile)) {
                    IOUtils.copy(is, zos);
                }
                zos.closeEntry();
            }

            // 添加下游PDF文件
            if (downstreamPdfFile.exists() && downstreamPdfFile.length() > 0) {
                String entryName = "downstream_excel_contents.pdf";
                zos.putNextEntry(new ZipEntry(entryName));
                try (InputStream is = new FileInputStream(downstreamPdfFile)) {
                    IOUtils.copy(is, zos);
                }
                zos.closeEntry();
            }
        }

        // 设置返回值
        resultMap.put("targetDir", newZipFile.getAbsolutePath());

        if (!resultMap.containsKey("supplierCompany")) {
            resultMap.put("supplierCompany", null); // 如果没有找到供应商公司名称，设置为null
        }

        return resultMap;
    }

    private static void processZipEntries(ZipFile zipFile, File workDir, Map<String, String> resultMap) throws IOException {
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            if (entry.isDirectory()) continue;

            String nameLower = entry.getName().toLowerCase();
            // 排除 macOS 资源目录与临时文件
            if (nameLower.startsWith("__macosx/") || nameLower.contains("/__macosx/")
                    || nameLower.endsWith("/.ds_store") || nameLower.contains("/.ds_store")
                    || nameLower.endsWith("/thumbs.db") || nameLower.startsWith("._")
                    || nameLower.substring(nameLower.lastIndexOf('/') + 1).startsWith("~$")) {
                continue;
            }

            if (!(nameLower.endsWith(".xls") || nameLower.endsWith(".xlsx"))) {
                // 只处理 Excel，其他文件忽略
                continue;
            }

            File targetFile = new File(workDir, entry.getName());
            if (targetFile.getParentFile() != null) targetFile.getParentFile().mkdirs();

            try (InputStream is = zipFile.getInputStream(entry);
                 OutputStream os = new FileOutputStream(targetFile)) {
                IOUtils.copy(is, os); // 原样复制，保留内容与样式
            }

            // 处理文件名修改：将"圣旦-金达"替换为数据库查询的公司名称
            String originalFileName = targetFile.getName();

            String newFileName = modifyFileName(originalFileName);
            if (!originalFileName.equals(newFileName)) {
                File newTargetFile = new File(targetFile.getParentFile(), newFileName);
                if (targetFile.renameTo(newTargetFile)) {
                    targetFile = newTargetFile;
                }
            }

            // 打开新保存的文件，根据第一个 Sheet 名称做定点修改
            if (!isRealExcelFile(targetFile)) {
                continue; // 扩展名为 xls/xlsx，但内容并非 Excel
            }

            try (FileInputStream fis = new FileInputStream(targetFile)) {
                Workbook wb = WorkbookFactory.create(fis);
                Sheet first = wb.getNumberOfSheets() > 0 ? wb.getSheetAt(0) : null;
                if (first != null) {
                    String sheetName = first.getSheetName();
                    if ("采购单".equals(sheetName)) {
                        // 读取B3单元格的原始值作为供应商公司名称
                        String supplierCompany = getCellStringValue(first, 2, 1);
                        // 将供应商公司名称存入结果Map
                        if (supplierCompany != null && !supplierCompany.trim().isEmpty()) {
                            resultMap.put("supplierCompany", supplierCompany);
                        }

                        // 使用查询到的公司名称更新B2和B3
                        setCellString(first, 1, 1,"成都燕北链方供应链管理有限公司");      // B2
                        setCellString(first, 2, 1,"圣旦（北京）云科技有限公司"); // B3
                        // F 列公式中 +19 改为 20.55
                        replacePlus19InFColumn(first);
                    } else {
                        setCellString(first, 44, 8, "20.55");             // I45
                    }
                }

                // 统一重算公式，确保跨 Sheet 依赖更新
                FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
                evaluator.evaluateAll();
                wb.setForceFormulaRecalculation(true);

                // 写入修改后的Excel文件
                try (FileOutputStream fos = new FileOutputStream(targetFile)) {
                    wb.write(fos);
                }
                wb.close();
            }
        }
    }

    /**
     * 从ZIP压缩包生成PDF文件
     * @param zipPath ZIP文件路径
     * @param pdfFile 目标PDF文件
     * @throws IOException
     * @throws DocumentException
     */
    private static void generatePdfFromZip(String zipPath, File pdfFile) throws IOException, DocumentException {
        // 初始化PDF文档，使用横向A4页面
        Document document = null;
        PdfWriter writer = null;
        FileOutputStream pdfOutputStream = null;

        try {
            Rectangle pageSize = PageSize.A4.rotate();
            pdfOutputStream = new FileOutputStream(pdfFile);
            document = new Document(pageSize, 10, 10, 30, 0); // 左右边距10，上边距30，下边距0
            writer = PdfWriter.getInstance(document, pdfOutputStream);
            document.open();

            List<Charset> charsetCandidates = Arrays.asList(
                    Charset.forName("UTF-8"),
                    Charset.forName("GBK"),
                    Charset.forName("CP437")
            );

            boolean processed = false;
            IllegalArgumentException lastIllegal = null;
            for (Charset cs : charsetCandidates) {
                ZipFile zf = null;
                try {
                    zf = new ZipFile(zipPath, cs);
                    processZipEntriesForPdf(zf, pdfFile.getParentFile(), document);
                    processed = true;
                    break;
                } catch (IllegalArgumentException iae) {
                    lastIllegal = iae; // 记录并尝试下一个 charset
                } finally {
                    if (zf != null) try {
                        zf.close();
                    } catch (IOException ignore) {
                    }
                }
            }
            if (!processed) {
                if (lastIllegal != null) throw lastIllegal; // 维持原始异常类型
                throw new IOException("Failed to read zip with all charset candidates");
            }
        } finally {
            // 确保PDF文档正确关闭，按照正确的资源释放顺序
            closePdfResources(document, writer, pdfOutputStream);
        }
    }

    /**
     * 处理ZIP条目并生成PDF内容
     * @param zipFile ZIP文件
     * @param workDir 工作目录
     * @param document PDF文档
     * @throws IOException
     */
    private static void processZipEntriesForPdf(ZipFile zipFile, File workDir, Document document) throws IOException {
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            if (entry.isDirectory()) continue;

            String nameLower = entry.getName().toLowerCase();
            // 排除 macOS 资源目录与临时文件
            if (nameLower.startsWith("__macosx/") || nameLower.contains("/__macosx/")
                    || nameLower.endsWith("/.ds_store") || nameLower.contains("/.ds_store")
                    || nameLower.endsWith("/thumbs.db") || nameLower.startsWith("._")
                    || nameLower.substring(nameLower.lastIndexOf('/') + 1).startsWith("~$")) {
                continue;
            }

            if (!(nameLower.endsWith(".xls") || nameLower.endsWith(".xlsx"))) {
                // 只处理 Excel，其他文件忽略
                continue;
            }

            // 为了生成PDF，临时保存文件
            File tempExcelFile = new File(workDir, "temp_" + UUID.randomUUID() + ".xlsx");
            try (InputStream is = zipFile.getInputStream(entry);
                 OutputStream os = new FileOutputStream(tempExcelFile)) {
                IOUtils.copy(is, os);
            }

            try {
                // 添加Excel文件名作为PDF
                document.newPage();
                // 转换Excel为PDF
                convertExcelToPdf(tempExcelFile, document);
            } finally {
                // 清理临时文件
                tempExcelFile.delete();
            }
        }
    }

    /**
     * 关闭PDF相关资源
     * @param document PDF文档
     * @param writer PDF写入器
     * @param outputStream 文件输出流
     */
    private static void closePdfResources(Document document, PdfWriter writer, FileOutputStream outputStream) {
        // 1. 先关闭Document，它会自动关闭PdfWriter
        if (document != null) {
            try {
                document.close();
            } catch (Exception e) {
                System.err.println("关闭PDF文档失败: " + e.getMessage());
            }
        }

        // 2. 确保PdfWriter关闭（虽然document.close()应该已经关闭了它）
        if (writer != null) {
            try {
                writer.close();
            } catch (Exception e) {
                System.err.println("关闭PdfWriter失败: " + e.getMessage());
            }
        }

        // 3. 确保底层文件输出流关闭
        if (outputStream != null) {
            try {
                outputStream.close();
            } catch (IOException e) {
                System.err.println("关闭PDF文件输出流失败: " + e.getMessage());
            }
        }
    }

    /**
     * 将Excel文件转换为PDF内容并添加到指定文档
     * 一个excel的内容添加到现有PDF文档中，一个sheet占用一页
     * @param excelFile Excel文件
     * @param document 目标PDF文档
     * @throws IOException
     */
    private static void convertExcelToPdf(File excelFile, Document document) throws IOException {
        // 创建中文字体
        BaseFont baseFont = null;
        Font font = null;
        Workbook workbook = null;
        FileInputStream fis = null;

        try {
            baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            font = new Font(baseFont, 11); // 使用较小字体以确保内容不换行

            // 读取Excel文件
            fis = new FileInputStream(excelFile);
            workbook = WorkbookFactory.create(fis);

            // 处理每个工作表（一个sheet一页）
            for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
                    Sheet sheet = workbook.getSheetAt(sheetIndex);
                    if (sheet == null) continue;

                    // 为每个sheet添加新页面（包括第一个sheet），确保每个sheet独立一页
                    document.newPage();

                    // 获取工作表的最大列数
                    int maxColumns = getMaxColumns(sheet);
                    if (maxColumns <= 0) continue;

                    // 创建PDF表格
                    PdfPTable table = new PdfPTable(maxColumns);

                    // 计算并设置列宽 - 保持等比例缩放
                    float pageWidth = PageSize.A4.rotate().getWidth() - document.leftMargin() - document.rightMargin();
                    table.setWidthPercentage(90); // 进一步缩小以防止变形，为内容提供足够空间

                    // 优化行高处理，避免内容压缩变形
                    table.setSpacingAfter(1f); // 行间距
                    table.setSpacingBefore(1f); // 表格间距
                    table.setHeaderRows(1); // 确保表头行正确处理

                    // 获取合并单元格信息
                    List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
                    boolean[][] mergedFlags = new boolean[sheet.getLastRowNum() + 1][maxColumns];

                    // 遍历工作表中的所有行
                    int lastRowNum = sheet.getLastRowNum();
                    for (int r = 0; r <= lastRowNum; r++) {
                        Row row = sheet.getRow(r);
                        if (row == null || row.getZeroHeight()) {
                            continue; // 跳过空行或隐藏行
                        }

                        // 遍历每一行的所有单元格
                        for (int c = 0; c < maxColumns; c++) {
                            // 跳过已经处理过的合并单元格
                            if (r < mergedFlags.length && c < mergedFlags[r].length && mergedFlags[r][c]) {
                                continue;
                            }

                            // 检查当前单元格是否是合并单元格的左上角
                            CellRangeAddress mergedRegion = findMergedRegion(mergedRegions, r, c);
                            if (mergedRegion != null) {
                                // 处理合并单元格
                                int firstRow = mergedRegion.getFirstRow();
                                int lastRow = mergedRegion.getLastRow();
                                int firstCol = mergedRegion.getFirstColumn();
                                int lastCol = mergedRegion.getLastColumn();

                                // 标记所有合并的单元格为已处理
                                for (int mr = firstRow; mr <= lastRow && mr < mergedFlags.length; mr++) {
                                    for (int mc = firstCol; mc <= lastCol && mc < mergedFlags[mr].length; mc++) {
                                        mergedFlags[mr][mc] = true;
                                    }
                                }

                                // 获取合并单元格的内容（通常在左上角单元格）
                                Cell cell = sheet.getRow(firstRow).getCell(firstCol);

                                boolean isRightmostColumn = (lastCol == maxColumns - 1);
                                boolean isLastRow = (lastRow == sheet.getLastRowNum());
                                PdfPCell pdfCell = createPdfCell(cell, font, sheet, isRightmostColumn, isLastRow, workbook, baseFont);

                                // 为合并单元格设置合适的最小高度，基于合并的行数
                                float totalRowHeight = 0;
                                for (int mr = firstRow; mr <= lastRow && mr <= sheet.getLastRowNum(); mr++) {
                                    Row mergeRow = sheet.getRow(mr);
                                    if (mergeRow != null && mergeRow.getHeight() > 0) {
                                        totalRowHeight += mergeRow.getHeightInPoints();
                                    }
                                }
                                if (totalRowHeight > 0) {
                                    pdfCell.setMinimumHeight(totalRowHeight * 0.9f); // 保持原始行高，不再压缩
                                }

                                // 设置合并单元格的行跨度和列跨度
                                pdfCell.setRowspan(lastRow - firstRow + 1);
                                pdfCell.setColspan(lastCol - firstCol + 1);

                                // 添加到PDF表格
                                table.addCell(pdfCell);
                            } else {
                                // 处理普通单元格 - 使用CREATE_NULL_AS_BLANK确保即使单元格为空也能创建Cell对象，以便正确应用边框样式
                                Cell cell = row.getCell(c, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                                boolean isRightmostColumn = (c == maxColumns - 1);
                                boolean isLastRow = (r == sheet.getLastRowNum());
                                PdfPCell pdfCell = createPdfCell(cell, font, sheet, isRightmostColumn, isLastRow, workbook, baseFont);

                                // 尝试根据Excel行高调整PDF单元格高度，保持比例
                                if (row.getHeight() > 0) {
                                    // 将Excel行高单位转换为适合PDF的值
                                    float excelRowHeight = row.getHeightInPoints();
                                    if (excelRowHeight > 0) {
                                        pdfCell.setMinimumHeight(excelRowHeight * 0.9f); // 保持原始行高，不再压缩
                                    }
                                }

                                table.addCell(pdfCell);
                            }
                        }
                    }

                    // 添加表格到文档
                    document.add(table);
                }
        } catch (DocumentException | IOException e) {
            throw new IOException("转换Excel到PDF失败: " + e.getMessage(), e);
        } finally {
            // 确保所有资源正确关闭
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    System.err.println("关闭Workbook失败: " + e.getMessage());
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    System.err.println("关闭文件输入流失败: " + e.getMessage());
                }
            }
        }
    }

    /**
     * 获取工作表的最大有内容列数，忽略全为空的列
     */
    private static int getMaxColumns(Sheet sheet) {
        // 首先标记哪些列有内容
        boolean[] hasContentColumns = new boolean[1000]; // 假设最多1000列
        int lastRowNum = sheet.getLastRowNum();
        int maxColIndex = 0;

        // 扫描所有行，标记有内容的列
        for (int r = 0; r <= lastRowNum; r++) {
            Row row = sheet.getRow(r);
            if (row != null) {
                maxColIndex = Math.max(maxColIndex, row.getLastCellNum());
                for (int c = 0; c < row.getLastCellNum(); c++) {
                    Cell cell = row.getCell(c, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
                    if (cell != null && !getCellDisplayValue(cell).trim().isEmpty()) {
                        hasContentColumns[c] = true;
                    }
                }
            }
        }

        // 找到最后一个有内容的列
        for (int c = maxColIndex - 1; c >= 0; c--) {
            if (hasContentColumns[c]) {
                return c + 1; // 返回列数（索引+1）
            }
        }

        return 0;
    }

    /**
     * 查找指定行列位置的合并单元格信息
     */
    private static CellRangeAddress findMergedRegion(List<CellRangeAddress> mergedRegions, int row, int col) {
        for (CellRangeAddress region : mergedRegions) {
            if (region.isInRange(row, col)) {
                return region;
            }
        }
        return null;
    }

    /**
     * 创建PDF单元格，保留Excel的格式和样式
     */
    private static PdfPCell createPdfCell(Cell cell, Font font, Sheet sheet, boolean isRightmostColumn, boolean isLastRow, Workbook workbook, BaseFont baseFont) {
        PdfPCell pdfCell = new PdfPCell();

        // 检查是否是采购单的H6单元格（H对应列索引7，行索引5（从0开始））
        boolean isPurchaseOrderH6 = "采购单".equals(sheet.getSheetName()) &&
                                   cell != null && cell.getRowIndex() == 5 && cell.getColumnIndex() == 7;

        // 检查是否是结算单的G4、G5、G6,G7单元格（G对应列索引6，行索引3-5（从0开始））
        boolean isSettlementOrderG4I5 = "结算单".equals(sheet.getSheetName()) &&
                                      cell != null && cell.getRowIndex() == 3 &&
                                      (cell.getColumnIndex() == 6 || cell.getColumnIndex() == 7 || cell.getColumnIndex() == 8 || cell.getColumnIndex() == 9);

        // 为采购单H6和结算单G4/H4/I4单元格设置自动换行
        pdfCell.setNoWrap(!(isPurchaseOrderH6 || isSettlementOrderG4I5));

        // 设置单元格内容 - 根据Excel单元格的字体样式创建对应的PDF字体
        String cellValue = getCellDisplayValue(cell);

        // 初始字体属性
        int fontStyle = Font.NORMAL;
        float fontSize =9f; // 默认字体大小

        // 如果单元格不为空且有样式，获取Excel中的字体样式
        if (cell != null) {
            CellStyle style = cell.getCellStyle();
            if (style != null) {
                try {
                    // 获取Excel字体信息 - 使用完全限定名以避免与iText Font类冲突
                    org.apache.poi.ss.usermodel.Font poiFont = null;

                    // 尝试使用不同的方法获取字体索引，以兼容不同版本的Apache POI
                    try {
                        // 尝试使用getFontIndexAsInt()方法（较新版本的POI）
                        Method getFontIndexAsIntMethod = style.getClass().getMethod("getFontIndexAsInt");
                        int fontIndex = (int) getFontIndexAsIntMethod.invoke(style);
                        poiFont = workbook.getFontAt(fontIndex);
                    } catch (NoSuchMethodException e1) {
                        try {
                            // 如果getFontIndexAsInt()不可用，尝试使用getFontIndex()方法（旧版本的POI）
                            Method getFontIndexMethod = style.getClass().getMethod("getFontIndex");
                            int fontIndex = (int) getFontIndexMethod.invoke(style);
                            poiFont = workbook.getFontAt(fontIndex);
                        } catch (NoSuchMethodException e2) {
                            // 如果两种方法都不可用，保持poiFont为null，使用默认字体设置
                            System.err.println("无法获取字体信息，使用默认设置: " + e2.getMessage());
                        }
                    }

                    // 设置字体大小和样式
                    if (poiFont != null) {
                        // 设置字体大小
                        fontSize = poiFont.getFontHeightInPoints();
                        // 设置字体样式（加粗等）
                        if (poiFont.getBold()) {
                            fontStyle = Font.BOLD;
                        }
                    }
                } catch (Exception e) {
                    // 如果获取字体信息失败，使用默认设置
                    System.err.println("获取字体信息失败: " + e.getMessage());
                }
            }
        }

        // 创建PDF字体
        Font pdfFont = new Font(baseFont, fontSize, fontStyle);
        // 设置单元格内容
        pdfCell.setPhrase(new Phrase(cellValue != null ? cellValue : "", pdfFont));

        // 设置对齐方式
        if (cell != null) {
            CellStyle style = cell.getCellStyle();
            if (style != null) {
                // 检查是否是发货单中的指定区域：A4-I4和A18
                boolean isInvoiceHeaderArea = "发货单".equals(sheet.getSheetName()) &&
                                           ((cell.getRowIndex() == 3 && cell.getColumnIndex() >= 0 && cell.getColumnIndex() <= 8) ||
                                            (cell.getRowIndex() == 16));

                // 如果是指定区域，应用背景颜色
                if (isInvoiceHeaderArea) {
                    try {
                        // 获取Excel单元格的填充背景颜色
                        short bgColorIndex = style.getFillForegroundColor();
                        // Excel的默认背景色索引为64（无填充），如果不是默认值则应用背景色
                        if (bgColorIndex != 64) {
                            // 创建PDF背景色
                            BaseColor bgColor;
                            // 根据Excel颜色索引获取RGB值（简化版，实际可能需要更复杂的颜色映射）
                            if (bgColorIndex == 42) { // 浅灰色
                                bgColor = new BaseColor(220, 220, 220);
                            } else if (bgColorIndex == 10) { // 黄色
                                bgColor = new BaseColor(255, 255, 0);
                            } else if (bgColorIndex == 9) { // 绿色
                                bgColor = new BaseColor(0, 255, 0);
                            } else if (bgColorIndex == 12) { // 红色
                                bgColor = new BaseColor(255, 0, 0);
                            } else {
                                // 尝试获取自定义颜色
                                try {
                                    // 使用反射获取工作簿的颜色调色板
                                    @SuppressWarnings("rawtypes")
                                    Class[] paramTypes = {short.class};
                                    Method getColorMethod = workbook.getClass().getMethod("getCustomColor", paramTypes);
                                    if (getColorMethod != null) {
                                        Object colorObj = getColorMethod.invoke(workbook, bgColorIndex);
                                        if (colorObj instanceof Color) {
                                            Color color = (Color) colorObj;
                                            bgColor = new BaseColor(color.getRed(), color.getGreen(), color.getBlue());
                                        } else {
                                            // 默认浅灰色作为后备
                                            bgColor = new BaseColor(220, 220, 220);
                                        }
                                    } else {
                                        // 默认浅灰色作为后备
                                        bgColor = new BaseColor(220, 220, 220);
                                    }
                                } catch (Exception e) {
                                    // 如果反射失败，使用默认浅灰色
                                    bgColor = new BaseColor(220, 220, 220);
                                }
                            }
                            // 设置PDF单元格背景色
                            pdfCell.setBackgroundColor(bgColor);
                            // 确保单元格使用背景色填充
                            pdfCell.setPadding(5);
                        }
                    } catch (Exception e) {
                        // 如果获取背景色失败，忽略错误继续处理
                        System.err.println("设置背景色失败: " + e.getMessage());
                    }
                }
                // 水平对齐
                switch (style.getAlignment()) {
                    case LEFT:
                        pdfCell.setHorizontalAlignment(Element.ALIGN_LEFT);
                        break;
                    case CENTER:
                        pdfCell.setHorizontalAlignment(Element.ALIGN_CENTER);
                        break;
                    case RIGHT:
                        pdfCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
                        break;
                    default:
                        pdfCell.setHorizontalAlignment(Element.ALIGN_LEFT);
                }

                // 垂直对齐
                switch (style.getVerticalAlignment()) {
                    case TOP:
                        pdfCell.setVerticalAlignment(Element.ALIGN_TOP);
                        break;
                    case CENTER:
                        pdfCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                        break;
                    case BOTTOM:
                        pdfCell.setVerticalAlignment(Element.ALIGN_BOTTOM);
                        break;
                    default:
                        pdfCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                }

                // 处理边框 - 只显示用户显式设置的边框，忽略Excel默认网格线
                // 初始化所有边框为无边框
                pdfCell.setBorderWidthTop(0f);
                pdfCell.setBorderWidthRight(0f);
                pdfCell.setBorderWidthBottom(0f);
                pdfCell.setBorderWidthLeft(0f);

                // 获取单元格边框样式和颜色
                CellStyle cellStyle = cell.getCellStyle();
                BorderStyle topBorderStyle = cellStyle.getBorderTop();
                BorderStyle rightBorderStyle = cellStyle.getBorderRight();
                BorderStyle bottomBorderStyle = cellStyle.getBorderBottom();
                BorderStyle leftBorderStyle = cellStyle.getBorderLeft();

                short topBorderColor = cellStyle.getTopBorderColor();
                short rightBorderColor = cellStyle.getRightBorderColor();
                short bottomBorderColor = cellStyle.getBottomBorderColor();
                short leftBorderColor = cellStyle.getLeftBorderColor();

                // 只显示非NONE样式且颜色不是自动颜色的边框（即用户显式设置的边框）
                // 注意：当borderColor=8并且borderStyle=NONE时，确保设置为无边框
                if ( !(topBorderStyle == BorderStyle.NONE && topBorderColor == 8)) {
                    pdfCell.setBorderWidthTop(0.5f);
                }

                // 为最右侧列添加右边框 - 只有当单元格实际有右边框样式时才添加
                if (isRightmostColumn) {
                     // 添加采购单B18单元格的特殊处理条件
                     boolean isPurchaseOrderB18 = "采购单".equals(cell.getSheet().getSheetName()) &&
                                                cell.getColumnIndex() == 1 &&
                                                cell.getRowIndex() == 17;

                     if (!(rightBorderStyle == BorderStyle.NONE && rightBorderColor == 8 && cellValue.isEmpty()) || isPurchaseOrderB18) {
                         pdfCell.setBorderWidthRight(0.5f);
                     }
                } else if (!(rightBorderStyle == BorderStyle.NONE && rightBorderColor == 8)) {
                    pdfCell.setBorderWidthRight(0.5f);
                }

                // 检查是否是最后一行，但排除borderColor=8且borderStyle=NONE的情况
                if (isLastRow && !(bottomBorderStyle == BorderStyle.NONE && bottomBorderColor == 8)) {
                    pdfCell.setBorderWidthBottom(0.5f);
                } else if ( !(bottomBorderStyle == BorderStyle.NONE && bottomBorderColor == 8)) {
                    pdfCell.setBorderWidthBottom(0.5f);
                }

                if ( !(leftBorderStyle == BorderStyle.NONE && leftBorderColor == 8)) {
                    pdfCell.setBorderWidthLeft(0.5f);
                }

                // 设置内边距
                pdfCell.setPadding(2); // 增加单元格内边距
            }
        }

        return pdfCell;
    }

    /**
     * 获取单元格显示值，处理数字大写格式
     */
    private static String getCellDisplayValue(Cell cell) {
        if (cell == null) return "";

        // 检查是否是发货单工作表的G15单元格（列索引6，行索引14）
        boolean isInvoiceG15= "发货单".equals(cell.getSheet().getSheetName()) &&
                             cell.getColumnIndex() == 6 &&
                             cell.getRowIndex() == 14;

        // 检查单元格是否有特殊格式（如中文大写数字或人民币格式）
        CellStyle style = cell.getCellStyle();
        String dataFormatString = null;
        boolean isCurrencyFormat = false;
        if (style != null) {
            DataFormat format = cell.getSheet().getWorkbook().createDataFormat();
            dataFormatString = format.getFormat(style.getDataFormat());

            // 检查是否是中文大写格式
            if (dataFormatString != null &&
                (dataFormatString.contains("[DBNum2]") ||
                 dataFormatString.contains("[DbNum1]") ||
                 dataFormatString.contains("壹"))) {
                // 对于中文大写格式，尝试转换为中文大写
                if (cell.getCellType() == CellType.NUMERIC) {
                    double value = cell.getNumericCellValue();
                    return convertToChineseCurrency(value);
                }
            }

            // 检查是否是人民币格式
            if (dataFormatString != null &&
                (dataFormatString.contains("¥") ||
                 dataFormatString.contains("\u00A5") || // Unicode人民币符号
                 dataFormatString.contains("[$$]") ||
                 dataFormatString.matches(".*#,##0\\.[0-9]+.*") || // 千位分隔符格式
                 dataFormatString.contains("Currency") ||
                 dataFormatString.contains("货币"))) {
                isCurrencyFormat = true;
            }
        }

        // 根据单元格类型获取值
        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    // 日期格式
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
                    return sdf.format(cell.getDateCellValue());
                } else {
                    // 数字格式，优化小数显示
                double value = cell.getNumericCellValue();

                    // 如果是人民币格式，应用人民币千位符格式
                      if (isCurrencyFormat) {
                          return "¥" + String.format("%,.2f", value);
                      }

                if (value == Math.floor(value)) {
                    return String.valueOf((long) value);
                } else {
                    // 判断是否需要保留两位小数
                    // 1. 检查是否是金额（通常最后两位小数非零）
                    // 2. 如果第二位小数是0，则只保留一位
                    double roundedToOne = Math.round(value * 10) / 10.0;
                    double roundedToTwo = Math.round(value * 100) / 100.0;

                    // 检查第二位小数是否为0
                    if (Math.abs(roundedToOne - roundedToTwo) < 0.001) {
                        return String.format("%.1f", roundedToOne);
                    } else {
                        // 金额或第二位小数非零，保留两位
                        return String.format("%.2f", roundedToTwo);
                    }
                    }
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                // 公式单元格获取计算结果
                try {
                    FormulaEvaluator evaluator = cell.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
                    CellValue cellValue = evaluator.evaluate(cell);
                    if (cellValue != null) {
                        switch (cellValue.getCellType()) {
                            case STRING:
                                return cellValue.getStringValue();
                            case NUMERIC:
                                double value = cellValue.getNumberValue();
                                // 检查是否需要中文大写
                                if (dataFormatString != null &&
                                    (dataFormatString.contains("[DBNum2]") ||
                                     dataFormatString.contains("壹"))) {
                                    return convertToChineseCurrency(value);
                                }

                                // 人民币格式或发货单G15单元格特殊处理：添加人民币符号并强制两位小数，包含千位分隔符
                                if (isCurrencyFormat || isInvoiceG15) {
                                    return "¥" + String.format("%,.2f", value);
                                }

                                if (value == Math.floor(value)) {
                                    return String.valueOf((long) value);
                                } else {
                                    // 公式结果也应用相同的小数格式化规则
                                    double roundedToOne = Math.round(value * 10) / 10.0;
                                    double roundedToTwo = Math.round(value * 100) / 100.0;

                                    if (Math.abs(roundedToOne - roundedToTwo) < 0.001) {
                                        return String.format("%.1f", roundedToOne);
                                    } else {
                                        return String.format("%.2f", roundedToTwo);
                                    }
                                }
                            case BOOLEAN:
                                return String.valueOf(cellValue.getBooleanValue());
                            default:
                                return "";
                        }
                    }
                } catch (Exception e) {
                    // 如果计算失败，返回原公式
                    return cell.getCellFormula();
                }
                return cell.getCellFormula();
            default:
                return "";
        }
    }

    /**
     * 将数字转换为中文货币大写
     */
    private static String convertToChineseCurrency(double value) {
        // 处理特殊值
        if (value == 0) return "零元整";

        // 检查范围
        if (value < 0 || value > 999999999999.99) {
            return String.valueOf(value);
        }

        // 处理正负号
        boolean isNegative = value < 0;
        value = Math.abs(value);

        // 分割整数和小数部分
        long integerPart = (long) value;
        int decimalPart = (int) Math.round((value - integerPart) * 100);

        // 中文数字字符
        String[] digits = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
        String[] units = {"", "拾", "佰", "仟"};
        String[] bigUnits = {"", "万", "亿"};

        StringBuilder result = new StringBuilder();

        // 处理负数
        if (isNegative) {
            result.append("负");
        }

        // 处理整数部分
        if (integerPart > 0) {
            String integerStr = String.valueOf(integerPart);
            int length = integerStr.length();

            for (int i = 0; i < length; i++) {
                int digit = integerStr.charAt(i) - '0';
                int position = length - i - 1;
                int unitIndex = position % 4;
                int bigUnitIndex = position / 4;

                if (digit != 0) {
                    // 如果前一位是0，添加零
                    if (i > 0 && integerStr.charAt(i - 1) == '0') {
                        result.append("零");
                    }
                    result.append(digits[digit]);
                    result.append(units[unitIndex]);
                }

                // 添加大单位（万、亿）
                if (unitIndex == 0 && digit != 0) {
                    result.append(bigUnits[bigUnitIndex]);
                }
            }

            result.append("元");
        }

        // 处理小数部分
        if (decimalPart > 0) {
            int jiao = decimalPart / 10;
            int fen = decimalPart % 10;

            if (jiao > 0) {
                result.append(digits[jiao]);
                result.append("角");
            }

            if (fen > 0) {
                result.append(digits[fen]);
                result.append("分");
            }
        } else {
            // 如果没有小数部分，添加"整"
            result.append("整");
        }

        return result.toString();
    }

    private static boolean isRealExcelFile(File file) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
            FileMagic fm = FileMagic.valueOf(bis);
            return fm == FileMagic.OLE2 || fm == FileMagic.OOXML;
        } catch (IOException e) {
            return false;
        }
    }

    private static void zipFolderRecursively(File root, File current, ZipOutputStream zos) throws IOException {
        File[] files = current.listFiles();
        if (files == null) return;
        for (File f : files) {
            if (f.isDirectory()) {
                zipFolderRecursively(root, f, zos);
            } else {
                // 排除PDF文件，因为已经单独处理
                if (!f.getName().toLowerCase().endsWith(".pdf")) {
                    String entryName = root.toPath().relativize(f.toPath()).toString().replace('\\', '/');
                    zos.putNextEntry(new ZipEntry(entryName));
                    try (InputStream is = new FileInputStream(f)) {
                        IOUtils.copy(is, zos);
                    }
                    zos.closeEntry();
                }
            }
        }
    }

    private static void setCellString(Sheet sheet, int rowIdx, int colIdx, String value) {
        Row row = sheet.getRow(rowIdx);
        if (row == null) row = sheet.createRow(rowIdx);
        Cell cell = row.getCell(colIdx, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
        CellStyle style = cell.getCellStyle();
        cell.setCellValue(value);
        if (style != null) cell.setCellStyle(style); // 保留原样式
    }

    private static String getCellStringValue(Sheet sheet, int rowIdx, int colIdx) {
        Row row = sheet.getRow(rowIdx);
        if (row == null) return null;
        Cell cell = row.getCell(colIdx, Row.MissingCellPolicy.RETURN_NULL_AND_BLANK);
        if (cell == null) return null;

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    return String.valueOf(cell.getNumericCellValue());
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                return cell.getCellFormula();
            default:
                return null;
        }
    }

    private static String modifyFileName(String originalFileName) {
        if (originalFileName != null && originalFileName.contains("供货单")) {
            // 满足条件，执行你要的逻辑
            /* 1. 抠出数字前缀（含点）  2. 拼新名字  3. 保留后缀 */
             // 提取文件后缀
             String extension = "";
             int dotIndex = originalFileName.lastIndexOf('.');
             if (dotIndex > 0) {
                 extension = originalFileName.substring(dotIndex);
             }

             // 修改文件名但保留后缀
             originalFileName = originalFileName
                   .replaceFirst("^(\\d+(?:\\.\\d+)*).*", "$1燕北-圣旦供货单") + extension;


        }
        return originalFileName;

    }

    private static void replacePlus19InFColumn(Sheet sheet) {
        int firstRow = sheet.getFirstRowNum();
        int lastRow  = sheet.getLastRowNum();
        int colF = 5; // F 列索引 0-based
        for (int r = firstRow; r <= lastRow; r++) {
            Row row = sheet.getRow(r);
            if (row == null) continue;
            Cell cell = row.getCell(colF, Row.MissingCellPolicy.RETURN_BLANK_AS_NULL);
            if (cell == null) continue;
            if (cell.getCellType() == CellType.FORMULA) {
                String formula = cell.getCellFormula();
                if (formula != null && formula.contains("+19")) {
                    cell.setCellFormula(formula.replace("+19", "+20.55"));
                }
            }
        }
    }
}
